package com.macro.mall.wx.service.impl;

import com.alibaba.fastjson.JSON;
import com.macro.mall.common.exception.ApiException;
import com.macro.mall.wx.domain.WxPayDTO;
import com.macro.mall.wx.sdk.*;
import com.macro.mall.wx.service.WxPayService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class WxPayServiceImpl implements WxPayService {
    @Autowired
    private WxBeanConfig wxBeanConfig;


    Logger logger = LoggerFactory.getLogger(WxPayService.class);

    @Override
    public Map<String, String> wxPay(WxPayDTO wxPayDTO) {
        if(wxPayDTO.getTrade_type().equals(WxMyConfig.TRADE_TYPE.JSAPI.VALUE())&& StringUtils.isBlank(wxPayDTO.getOpenid())){
            throw new ApiException("微信支付openid不能为空");
        }
        // 把请求参数打包成数组
        Map<String, String> paraMap = JSON.parseObject(JSON.toJSONString(wxPayDTO),Map.class);
        if (StringUtils.isBlank(wxPayDTO.getOpenid())){
            paraMap.remove("openid");
        }
        // 商家名称-销售商品类目、String(128)
        logger.info("paraMap为：" + paraMap);
        logger.info("================ 分隔线 ==============");
        final String SUCCESS_NOTIFY = this.wxBeanConfig.getNotifyUrl();
        boolean useSandbox = false;
        // 是否使用沙盒环境支付API，是的话不会真正扣钱
        WXPayConfig config = WxMyConfig.getInstance(wxBeanConfig);
        WXPay wxPay = null;
        try {
            wxPay = new WXPay(config, SUCCESS_NOTIFY, false, useSandbox);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 3. fillRequestData会将上述参数用key=value形式和mchKey一起加密为sign，验证地址：https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1
        Map<String, String> map = null;
        try {
            map = wxPay.unifiedOrder(paraMap, 15000, 15000);
            logger.info("=====================================================================付款结果=====================================================================" + map);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String, String> payMap = new HashMap<String, String>();
        if(map!=null){
            if(map.get("result_code").equals("FAIL")){
               throw new ApiException(map.get("err_code_des"));
            }
            // 4. 发送post请求"统一下单接口"(https://api.mch.weixin.qq.com/pay/unifiedorder), 返回预支付id:prepay_id
            String prepayId =  map.get("prepay_id");
            logger.info("xmlStr为：" + map);
            logger.info("================ 分隔线 ==============");
            payMap.put("appId", this.wxBeanConfig.getAppId());
            payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp() + "");
            payMap.put("nonceStr", WXPayUtil.generateNonceStr());
            if (useSandbox) {
                payMap.put("signType", WXPayConstants.MD5);
            } else {
                payMap.put("signType", WXPayConstants.MD5);
            }
            payMap.put("package", "prepay_id=" + prepayId);
            // 5. 通过appId, timeStamp, nonceStr, signType, package及商户密钥进行key=value形式拼接并加密
            String paySign = null;
            try {
                if (useSandbox) {
                    paySign = WXPayUtil.generateSignature(payMap, this.wxBeanConfig.getKey(), WXPayConstants.SignType.HMACSHA256);
                } else {
                    paySign = WXPayUtil.generateSignature(payMap, this.wxBeanConfig.getKey(), WXPayConstants.SignType.MD5);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            if(wxPayDTO.getTrade_type().equals(WxMyConfig.TRADE_TYPE.MWEB.VALUE())){
                payMap.put("trade_type",map.get("trade_type"));
                payMap.put("prepay_id",map.get("prepay_id"));
                payMap.put("mweb_url",map.get("mweb_url"));
            }
            payMap.put("paySign", paySign);
            // 6. 将这个6个参数传给前端
            logger.info("payMap：" + payMap);
        }
        return payMap;
    }
}
